from typing import Any, Dict, Optional, Callable, AsyncGenerator
import asyncio
from .json_utils import json_dumps
from .content import ContentProcessor
from .logger import get_default_logger


class Response:
    """统一响应 - 使用ContentProcessor消除重复逻辑"""

    def __init__(
        self, content: Any, status: int = 200, headers: Optional[Dict[str, str]] = None
    ):
        self.content = content
        self.status = status
        # 使用统一内容处理器 - 消除重复逻辑
        self.headers = ContentProcessor.prepare_headers(content, headers)
        self.body = ContentProcessor.process_content(content)

    async def send(self, send: Callable):
        """发送响应"""
        # 确保headers符合ASGI规范：字节对列表
        header_pairs = []
        for k, v in self.headers.items():
            try:
                header_pairs.append((k.encode('utf-8'), v.encode('utf-8')))
            except Exception as e:
                # 如果编码失败，跳过这个header
                logger = get_default_logger()
                logger.warn(
                    "流式响应头编码失败，跳过此头部",
                    event="stream_response_header_encoding_failed",
                    header_name=k,
                    header_value=str(v)[:50] if v else "",
                    encoding_error=str(e)
                )
        
        await send({
            "type": "http.response.start",
            "status": self.status,
            "headers": header_pairs
        })
        await send({"type": "http.response.body", "body": self.body, "more_body": False})


# 便捷函数，没有类继承
def JSON(content: Any, status: int = 200) -> Response:
    return Response(content, status, {"content-type": "application/json; charset=utf-8"})


def HTML(content: str, status: int = 200) -> Response:
    return Response(content, status, {"content-type": "text/html; charset=utf-8"})


def Text(content: str, status: int = 200) -> Response:
    return Response(content, status, {"content-type": "text/plain; charset=utf-8"})


class StreamResponse(Response):
    """流式响应 - 扩展而非替换"""
    
    def __init__(self, content_generator: AsyncGenerator, status=200, headers=None, buffer_size=8192):
        # 不调用父类__init__，避免立即处理内容
        self.content_generator = content_generator  # 可以是async generator
        self.status = status
        self.buffer_size = buffer_size
        
        # Linus式修复：基于buffer_size的语义一致性缓存控制
        stream_headers = self._get_cache_headers(buffer_size)
        
        # 确保Content-Type包含UTF-8编码声明 - 修复中文乱码
        stream_headers["content-type"] = "text/plain; charset=utf-8"
        
        # 合并自定义头部
        if headers:
            stream_headers.update(headers)
            
        self.headers = stream_headers
    
    def _get_cache_headers(self, buffer_size: int) -> dict:
        """根据缓冲区大小生成语义一致的缓存控制头"""
        if buffer_size == 0:
            # 真正的实时模式：无缓冲，禁用所有缓存
            return {
                "cache-control": "no-cache, no-store, must-revalidate, max-age=0",
                "pragma": "no-cache",
                "expires": "0",
                "x-accel-buffering": "no",  # 禁用Nginx缓冲
                "connection": "keep-alive",
                # 添加更多禁用浏览器缓冲的头部
                "x-content-type-options": "nosniff",
                "x-xss-protection": "1; mode=block",
                "transfer-encoding": "chunked",  # 明确指定分块传输
            }
        elif buffer_size <= 4096:
            # 小缓冲模式：短期缓存，允许1秒缓存
            return {
                "cache-control": "private, max-age=1, must-revalidate",
                "x-accel-buffering": "no",  # 仍禁用Nginx缓冲
                "connection": "keep-alive",
                "transfer-encoding": "chunked",
            }
        elif buffer_size <= 16384:
            # 中等缓冲模式：中期缓存，允许5秒缓存
            return {
                "cache-control": "private, max-age=5, must-revalidate",
                "x-accel-buffering": "no",  # 仍禁用Nginx缓冲
                "connection": "keep-alive",
                "transfer-encoding": "chunked",
            }
        else:
            # 大缓冲模式：长期缓存，允许30秒缓存
            return {
                "cache-control": "private, max-age=30, must-revalidate",
                "connection": "keep-alive",
                "transfer-encoding": "chunked",
            }
        
    async def send(self, send: Callable):
        """流式发送 - 覆盖父类方法"""
        from .streaming import StreamSender, GuaStreamError
        
        sender = StreamSender(send, self.buffer_size)
        
        try:
            # 发送头部
            # 确保headers符合ASGI规范：字节对列表
            header_pairs = []
            for k, v in self.headers.items():
                try:
                    header_pairs.append((k.encode('utf-8'), v.encode('utf-8')))
                except Exception as e:
                    # 如果编码失败，跳过这个header
                    logger = get_default_logger()
                    logger.warn(
                        "流式响应头编码失败，跳过此头部",
                        event="stream_response_header_encoding_failed",
                        header_name=k,
                        header_value=str(v)[:50] if v else "",
                        encoding_error=str(e)
                    )
            
            await send({
                "type": "http.response.start",
                "status": self.status,
                "headers": header_pairs
            })
            
            # 流式发送内容
            async for chunk in self.content_generator:
                await sender.send_chunk(chunk, is_sse=False)
                
            # 结束流
            await sender.finish()
            
        except GuaStreamError as e:
            # 流式处理错误 - 已经格式化的错误
            logger = get_default_logger()
            logger.error(
                "流式响应发生GuaStreamError",
                event="stream_response_gua_error",
                error=str(e),
                user_impact="用户将看到流式错误信息"
            )
            await send({
                "type": "http.response.start",
                "status": 500,
                "headers": [(b"content-type", b"application/json; charset=utf-8")]
            })
            await send({
                "type": "http.response.body",
                "body": f'{{"error": "{str(e)}"}}'.encode('utf-8'),
                "more_body": False
            })
        except (ConnectionError, OSError, asyncio.TimeoutError) as e:
            # 连接错误 - 不需要发送响应，客户端已经断开
            logger = get_default_logger()
            logger.warn(
                "流式响应时连接丢失",
                event="stream_response_connection_lost",
                connection_error=str(e),
                user_impact="用户连接已断开，这是正常情况"
            )
            pass
        except Exception as e:
            # 其他未知错误
            logger = get_default_logger()
            logger.error(
                "流式响应发生未知错误",
                event="stream_response_unknown_error",
                error=str(e),
                error_type=type(e).__name__,
                user_impact="用户将看到内部服务器错误"
            )
            await send({
                "type": "http.response.start",
                "status": 500,
                "headers": [(b"content-type", b"application/json; charset=utf-8")]
            })
            await send({
                "type": "http.response.body",
                "body": f'{{"error": "Internal stream error: {str(e)}"}}'.encode('utf-8'),
                "more_body": False
            })


class SSEResponse(StreamResponse):
    """服务器发送事件响应 - 特殊的流式响应"""
    
    def __init__(self, event_generator: AsyncGenerator, status=200, headers=None, retry=3000, buffer_size=8192):
        # 创建格式化后的SSE事件生成器
        self.formatted_generator = self._format_sse_events(event_generator)
        
        # 调用父类__init__，利用新的缓存控制逻辑
        super().__init__(self.formatted_generator, status, headers, buffer_size)
        
        # 覆盖content-type为SSE专用
        self.headers["content-type"] = "text/event-stream; charset=utf-8"
        
        # SSE特有的CORS头部
        self.headers.update({
            "access-control-allow-origin": "*",
            "access-control-allow-headers": "Cache-Control",
        })
        
        # 对于SSE，通常需要禁用Nginx缓冲以确保事件及时到达
        self.headers["x-accel-buffering"] = "no"
        
        self.retry = retry  # 重连间隔（毫秒）
    
    async def send(self, send: Callable):
        """SSE专用发送 - 使用StreamSender确保缓冲机制生效"""
        from .streaming import StreamSender, GuaStreamError
        
        # Linus式修复：SSE也应该使用StreamSender来确保buffer_size生效
        sender = StreamSender(send, self.buffer_size)
        
        try:
            # 发送头部
            # 确保headers符合ASGI规范：字节对列表
            header_pairs = []
            for k, v in self.headers.items():
                try:
                    header_pairs.append((k.encode('utf-8'), v.encode('utf-8')))
                except Exception as e:
                    # 如果编码失败，跳过这个header
                    logger = get_default_logger()
                    logger.warn(
                        "SSE响应头编码失败，跳过此头部",
                        event="sse_response_header_encoding_failed",
                        header_name=k,
                        header_value=str(v)[:50] if v else "",
                        encoding_error=str(e)
                    )
            
            await send({
                "type": "http.response.start",
                "status": self.status,
                "headers": header_pairs
            })
            
            # SSE专用流式发送 - 使用StreamSender确保缓冲机制生效
            async for chunk in self.content_generator:
                # 使用StreamSender发送SSE格式化后的数据，确保缓冲机制生效
                await sender.send_chunk(chunk, is_sse=True)
                
            # 结束流
            await sender.finish()
            
        except GuaStreamError as e:
            # 流式处理错误 - 已经格式化的错误
            logger = get_default_logger()
            logger.error(
                "SSE响应发生GuaStreamError",
                event="sse_response_gua_error",
                error=str(e),
                user_impact="用户将看到SSE错误事件"
            )
            await send({
                "type": "http.response.start",
                "status": 500,
                "headers": [(b"content-type", b"text/event-stream")]
            })
            await send({
                "type": "http.response.body",
                "body": f'event: error\ndata: {str(e)}\n\n'.encode('utf-8'),
                "more_body": False
            })
        except (ConnectionError, OSError, asyncio.TimeoutError) as e:
            # 连接错误 - 不需要发送响应，客户端已经断开
            logger = get_default_logger()
            logger.warn(
                "SSE响应时连接丢失",
                event="sse_response_connection_lost",
                connection_error=str(e),
                user_impact="用户SSE连接已断开，这是正常情况"
            )
            pass
        except Exception as e:
            # 其他未知错误
            logger = get_default_logger()
            logger.error(
                "SSE响应发生未知错误",
                event="sse_response_unknown_error",
                error=str(e),
                error_type=type(e).__name__,
                user_impact="用户将看到SSE内部错误事件"
            )
            await send({
                "type": "http.response.start",
                "status": 500,
                "headers": [(b"content-type", b"text/event-stream")]
            })
            await send({
                "type": "http.response.body",
                "body": f'event: error\ndata: Internal SSE error: {str(e)}\n\n'.encode('utf-8'),
                "more_body": False
            })
        
    async def _format_sse_events(self, event_generator: AsyncGenerator):
        """格式化SSE事件 - 处理SSE协议细节，支持预格式化事件"""
        # 发送重连配置
        yield f"retry: {self.retry}\n\n"
        
        async for event in event_generator:
            # 如果事件已经是预格式化的SSE字符串，直接yield
            if isinstance(event, str) and event.startswith(('event:', 'data:', 'retry:', 'id:')):
                # 预格式化的SSE事件，直接发送
                yield event
                # 确保事件后立即刷新
                await asyncio.sleep(0)  # 让出控制权，确保立即发送
            elif isinstance(event, str):
                # 简单字符串事件 - 确保UTF-8编码
                yield f"data: {event}\n\n"
            elif isinstance(event, dict):
                # 结构化事件
                event_str = ""
                if "event" in event:
                    event_str += f"event: {event['event']}\n"
                if "id" in event:
                    event_str += f"id: {event['id']}\n"
                if "retry" in event:
                    event_str += f"retry: {event['retry']}\n"
                if "data" in event:
                    data = event['data']
                    if isinstance(data, (dict, list)):
                        # JSON数据自动序列化，确保UTF-8编码
                        data_str = json_dumps(data)
                    else:
                        data_str = str(data)
                    # 多行数据需要每行前加"data: "
                    for line in data_str.split('\n'):
                        event_str += f"data: {line}\n"
                event_str += "\n"  # 事件结束
                yield event_str
            else:
                # 其他类型转换为字符串
                yield f"data: {str(event)}\n\n"
            
            # 强制刷新，确保实时性
            await asyncio.sleep(0)


# 便捷函数，保持API一致性
def Stream(content_generator: AsyncGenerator, status=200, headers=None, buffer_size=8192):
    """创建流式响应"""
    return StreamResponse(content_generator, status, headers, buffer_size)


def SSE(content_generator: AsyncGenerator, status=200, headers=None, retry=3000, buffer_size=8192):
    """创建服务器发送事件响应"""
    return SSEResponse(content_generator, status, headers, retry, buffer_size)


# SSE事件构建器 - 提供更友好的API
class SSEEvent:
    """SSE事件构建器 - 类型安全的事件创建"""
    
    def __init__(self, data=None, event=None, id=None, retry=None):
        self.data = data
        self.event = event
        self.id = id
        self.retry = retry
        
    def to_dict(self):
        """转换为字典格式"""
        result = {}
        if self.data is not None:
            result['data'] = self.data
        if self.event is not None:
            result['event'] = self.event
        if self.id is not None:
            result['id'] = self.id
        if self.retry is not None:
            result['retry'] = self.retry
        return result


# 便捷函数
def sse_event(data, event=None, id=None, retry=None):
    """创建SSE事件"""
    return SSEEvent(data, event, id, retry).to_dict()


# 常用SSE事件类型
def sse_ping():
    """心跳事件"""
    return sse_event("ping", event="heartbeat")


def sse_error(message, id=None):
    """错误事件"""
    return sse_event({"error": message}, event="error", id=id)


def sse_update(data, id=None):
    """数据更新事件"""
    return sse_event(data, event="update", id=id)
